# -*- encoding: utf-8 -*-
"""
File Name: dedicated_line_monitor
Description:
Author : 'lirui'
date: 2024/1/26
Contact: marjey_lee@163.com
Change Activity:
2024/1/26:
"""
import time
from threading import Thread

import ll
from projects.monitoring.common.utils.redis_problem_publishers_manager import RedisProblemsPublishersManager
from projects.monitoring.dedicated_line_monitor.utils.load_cmdb_info import load_dedicated_info_from_cmdb
from projects.monitoring.dedicated_line_monitor.utils.router_connection import build_router_connection, build_router_connection_mapping

ll.get_logger().warning('Deprecated code, please use new version code.')


class DedicatedLineMonitor(Thread):
    def __init__(self):
        super().__init__()
        self.monitor_items = None
        self.results = {}
        self.router_connection_mapping = build_router_connection_mapping()
        self.health_check = 1

    def run(self):
        while True:
            try:
                self()
                self.health_check = 1
            except Exception as e:
                ll.get_logger().error(e)
                self.health_check = 0

    def __call__(self):
        """
        monitor dedicated line
        """
        ll.get_logger().info('Start monitor dedicated line.')
        self.monitor_items = load_dedicated_info_from_cmdb()
        check_res = {}
        for line_info in self.monitor_items:
            ip = line_info['opposite_ip_address']
            router = line_info['router']
            name = line_info['institution']
            ll.get_logger().debug(f'Start to check {name}')
            if 'FD_YNKM_EXT_Other' in router:
                continue
            time.sleep(0.1)
            if self._check_ping(ip, router):  # success
                self.results[f'{ip}-{router}'] = 1
                continue
            else:
                self.results[f'{ip}-{router}'] = 0
                check_res[name + '-' + ip] = dict(
                    timestamp=time.time(),
                    router=router,
                    ip=ip,
                    name=name,
                    importance=line_info['importance']
                )
        self._send_problems_to_redis(check_res)

    @staticmethod
    def _send_problems_to_redis(problems):
        """
        send problems to redis.
        Args:
            problems:

        Returns:

        """
        RedisProblemsPublishersManager.publish(
            key='dedicated_line_monitor',
            content=problems
        )

    def _check_ping(self, ip, router_name):
        """

        Args:
            ip:
            router_name:

        Returns:

        """
        ll.get_logger().debug(f'Start to check ping {ip} through {router_name}.')
        if router_name not in self.router_connection_mapping:
            self.router_connection_mapping[router_name] = build_router_connection(router_name)
        if router_name not in self.router_connection_mapping:
            ll.get_logger().warning(f'{router_name} connection failed.')
            return False
        if not self._check_connection(self.router_connection_mapping[router_name]):
            self.router_connection_mapping[router_name] = build_router_connection(router_name)
            if not self._check_connection(self.router_connection_mapping[router_name]):
                ll.get_logger().error(f'check connection {router_name} error.')
                return False
        cmd = f'ping -c 2 {ip}'
        for i in range(3):
            try:
                res = self.router_connection_mapping[router_name].send_command(
                    cmd,
                    read_timeout=30
                )
                if ' 0.00% packet loss' in res or ' 0.0% packet loss':
                    return True
            except Exception as e:
                ll.get_logger().warning(e)
        return False

    def disconnection(self):
        for router, v in self.router_connection_mapping:
            v.disconnect()

    @staticmethod
    def _check_connection(connection):
        if connection is None:
            return False
        for _ in range(3):
            try:
                output = connection.send_command(
                    'ping  -c 1 127.0.0.1',
                    read_timeout=30,
                )
                if 'received' in output:
                    return True
            except Exception as e:
                ll.get_logger().warning(e)
        return False


def _main():
    monitor = DedicatedLineMonitor()
    monitor()


if __name__ == '__main__':
    _main()
